package model.service;

import java.util.ArrayList;

import com.google.zxing.Result;

import model.Coordinate;
import model.Dimension;
import model.OnScreen;
import model.location.WorldCoordinate;

public class ServiceCalculator 
{
	public static void calculateClippingPane(ArrayList<Result> acceptedResults) //throws Exception
	{
		//Gets 2 QR-codes
		ServiceRefPoint firstInArray = new ServiceRefPoint(acceptedResults.get(0));
		ServiceRefPoint secondInArray = new ServiceRefPoint(acceptedResults.get(1));
		
		updateLeftToRightScale(firstInArray, secondInArray);
		
		double[] scales = calculateScale(firstInArray, secondInArray);		
		WorldCoordinate[] screenBoundsInWorld = calculateBounds(firstInArray.getWorldCoordinate(), firstInArray.getScreenCoordinate(), scales);		
		
//		calculateAngle(xWorldDistance,(int) (xScreenDistance * scaleX));
		
		OnScreen.getInstance().updateScreenCoordinates(screenBoundsInWorld[0], screenBoundsInWorld[1]);
	}
	
//	public static void calculateAngle(int realWorldDistance, int screenWorldDistance)
//    {
//		
//    	int aanliggend = Math.abs(screenWorldDistance);
//    	int schuin = Math.abs(realWorldDistance);
//    	
//    	double ratio = (double) aanliggend / (double) schuin;
//    	
//    	float angle = (float) Math.acos(ratio);
//    	
//    	angle = (float) Math.toDegrees(angle);
//    	
//    	Log.d("ANGLE", String.format("aanliggend: %d - schuin: %d - ratio: %f - angle: %f", aanliggend,schuin, (float) ratio,angle));
//    	
//    	OnScreen.getInstance().setAngle(angle);
//    }
	
	private static WorldCoordinate[] calculateBounds(WorldCoordinate codeWorldLocation, Coordinate codeScreenLocation, double[] scales)
	{
		int ULX = (int) (codeWorldLocation.getX() - (codeScreenLocation.getX() * scales[0]));
		int ULY = (int) (codeWorldLocation.getY() + (codeScreenLocation.getY() * scales[1]));
		int ULZ = codeWorldLocation.getZ();
		
		WorldCoordinate upperLeft = new WorldCoordinate(ULX,ULY,ULZ);
		
		Dimension dim = OnScreen.getInstance().getScreenDimension();
		
		int LRX = (int) (codeWorldLocation.getX() + ((dim.getWidth() - codeScreenLocation.getX()) * scales[0]));
		int LRY = (int) (codeWorldLocation.getY() - ((dim.getHeight() - codeScreenLocation.getY()) * scales[1]));
		int LRZ = codeWorldLocation.getZ();
		
		WorldCoordinate lowerRight = new WorldCoordinate(LRX,LRY,LRZ);
		
		return new WorldCoordinate[]{upperLeft,lowerRight};
		
	}

	private static void updateLeftToRightScale(ServiceRefPoint first, ServiceRefPoint second)
	{
		if(first.getScreenCoordinate().getX() < second.getScreenCoordinate().getX()) 
		{
			float leftToRightScale = (float) ( (float)first.getHeight() / (float)second.getHeight());
			OnScreen.getInstance().setLeftToRightCodeScale(leftToRightScale);
		}
		else
		{
			float leftToRightScale = (float) ( (float)second.getHeight() / (float)first.getHeight());
			OnScreen.getInstance().setLeftToRightCodeScale(leftToRightScale);			
		}
	}

	private static double[] calculateScale(ServiceRefPoint first, ServiceRefPoint second)
	{
		//calculate distance between codes in pixels
		int xScreenDistance = second.getScreenCoordinate().getX() - first.getScreenCoordinate().getX();
		int yScreenDistance = second.getScreenCoordinate().getY() - first.getScreenCoordinate().getX();
		
		//calculate actual distance between codes in cm
		int xWorldDistance = second.getScreenCoordinate().getX() - first.getScreenCoordinate().getX();
		int yWorldDistance = first.getScreenCoordinate().getY() - second.getScreenCoordinate().getY();
		
		//calculate scale
		double scaleX =  (double) xWorldDistance /  (double) xScreenDistance;
		double scaleY =  (double) yWorldDistance /  (double) yScreenDistance;
		
		return new double[]{scaleX, scaleY};
	}
}